﻿namespace MtmDeepCopy
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Data;
    using System.Xml;
    using System.Xml.Linq;
    using Microsoft.TeamFoundation.Client;
    using Microsoft.TeamFoundation.TestManagement.Client;
    using Microsoft.TeamFoundation.WorkItemTracking.Client;
    using MtmDeepCopy.ViewModels;
    using Sogeti.QueryWrapper;
    using Sogeti.VSExtention;

    public delegate XmlElement CopyNodeDelagate(XmlElement source, XmlElement targetParent);

    public class WorkItemFields : INotifyPropertyChanged
    {
        public WorkItemFields()
        {
            FieldName = string.Empty;
            RefName = string.Empty;
            AllowedValues = new List<KeyValuePair<string, string>>();
        }

        public string FieldName { get; set; }

        public string RefName { get; set; }

        public bool HasAllowedValues
        {
            get
            {
                return AllowedValues.Count > 0;
            }
        }

        public List<KeyValuePair<string, string>> AllowedValues 
        {
            get;
            set;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }

    public class WIFieldValue : INotifyPropertyChanged
    {
        private WorkItemFields _field;

        public WIFieldValue()
        {
            Field = new WorkItemFields();
            Value = string.Empty;
        }

        public WorkItemFields Field 
        { 
            get
            {
                return _field;
            }
            
            set
            {
                _field = value;
                NotifyPropertyChanged("Field");
            }
        }

        public string Value { get; set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }

    public class MTMViewModel : INotifyPropertyChanged
    {
        #region "Private fields"
        
        private string chgStructType;
        
        private bool _createTargetTestPlan;
       
        private WIQLQueryItems _QueryStructure;
        private ObservableCollection<WIFieldValue> _lstChangeField;
        private List<WorkItemFields> _lstWorkItemFields;
     
        #endregion

        public MTMViewModel()
        {
            Actions = new List<IAction>();

            TestPlan tpSource = new TestPlan(this);
            SourceTestPlan = tpSource;

            TestPlan tpTarget = new TestPlan(this);
            TargetTestPlan = tpTarget;

            LstChangeField = new ObservableCollection<WIFieldValue>();
        }

        public MTMViewModel(Uri sourceUri, string sourceTP, Uri targetUri, string targetTP)
        {
            Actions = new List<IAction>();

            TestPlan tpSource = new TestPlan(this);
            
            ConnectTeamProject(ref tpSource, sourceUri, sourceTP);
            SourceTestPlan = tpSource;

            TestPlan tpTarget = new TestPlan(this);
            ConnectTeamProject(ref tpTarget,  targetUri, targetTP);
            TargetTestPlan = tpTarget;

            LstChangeField = new ObservableCollection<WIFieldValue>();
            LstChangeField.Add(new WIFieldValue() { Field = LstWorkItemFields[0] });
        }

        #region "Public properties"
     
        public bool CreateTargetTestPlan
        {
            get
            {
                return _createTargetTestPlan;
            }

            set
            {
                _createTargetTestPlan = value;
                NotifyPropertyChanged("CreateTargetTestPlan");
            }
        }

        public bool isTreeviewReadyForCopy
        {
            get { return (TargetTestPlan.TestSuites != null && SourceTestPlan.TestSuites != null && TargetTestPlan.SelectedNode != null && (TargetTestPlan.SelectedNode.Attributes["Type"].Value == "StaticTestSuite" || TargetTestPlan.SelectedNode.Attributes["Type"].Value == "RequirementTestSuite" || TargetTestPlan.SelectedNode.Name == "TestPlan")); }
        }

        public bool isReadyForNewSuite
        {
            get { return (TargetTestPlan.TestSuites != null && TargetTestPlan.SelectedNode != null && (TargetTestPlan.SelectedNode.Attributes["Type"].Value == "StaticTestSuite"  || TargetTestPlan.SelectedNode.Name == "TestPlan")); }
        }

        public ObservableCollection<WIFieldValue> LstChangeField 
        {
            get
            {
                return _lstChangeField;
            }
            
            set
            {
                _lstChangeField = value;
                NotifyPropertyChanged("LstChangeField");
            }
        }

        public string SelectedChangeStructureType
        {
            get
            {
                return chgStructType;
            }

            set
            {
                chgStructType = value;
                NotifyPropertyChanged("SelectedChangeStructureType");
                NotifyPropertyChanged("StructureNodes");
            }
        }

        public List<WorkItemFields> LstWorkItemFields
        {
            get
            {
                if (_lstWorkItemFields == null)
                {
                    List<WorkItemFields> lst = new List<WorkItemFields>();

                    if (this.TargetTestPlan.TeamProjectCollection != null && TargetTeamProject != null)
                    {
                        _lstWorkItemFields = LoadFields(this.TargetTestPlan.TeamProjectCollection, TargetTeamProject);
                    }
                }

                return _lstWorkItemFields;
            }

            set
            {
                _lstWorkItemFields = value;
                NotifyPropertyChanged("LstWorkItemFields");
            }
        }

        public NodeCollection StructureNodes
        {
            get
            {
                if (SelectedChangeStructureType == string.Empty)
                {
                    return null;
                }
                else
                {
                    if (TargetTestPlan.TeamProjectCollection != null && TargetTeamProject != null)
                    {
                        WorkItemStore wiStore = (WorkItemStore)TargetTestPlan.TeamProjectCollection.GetService(typeof(WorkItemStore));
                        return SelectedChangeStructureType == "System.IterationPath" ? wiStore.Projects[TargetTeamProject].IterationRootNodes : wiStore.Projects[TargetTeamProject].AreaRootNodes;
                    }

                    return null;
                }
            }
        }

        public string SelectedStructureNode { get; set; }

        public bool CopyRecursive { get; set; }
        
        public bool CopyRequirement { get; set; }

        public bool ConvRequirementToStatic { get; set; }

        public string SourceTeamProject
        {
            get
            {
                return SourceTestPlan.TeamProject;
            }

            set
            {
                SourceTestPlan.TeamProject = value;
                NotifyPropertyChanged("QueryStructure");
                
                if (TargetTeamProject == null)
                {
                    TargetTeamProject = SourceTeamProject;
                }
            }
        }

        public TestPlan SourceTestPlan
        {
            get;
            set;
        }

        public TestPlan TargetTestPlan
        {
            get;
            set;
        }

        public WIQLQueryItems QueryStructure
        {
            get
            {
                if (SourceTestPlan.TeamProjectCollection != null)
                {
                    TPQueryWrapper qw = new TPQueryWrapper(SourceTestPlan.TeamProjectCollection.Uri.ToString(), SourceTestPlan.TeamProject);
                    _QueryStructure = qw.ReadQueryStructure(SourceTeamProject + @"/" + qw.TeamQueryFolderName);
                }

                return _QueryStructure;
            }

            set
            {
                _QueryStructure = value;
                NotifyPropertyChanged("QueryStructure");
            }
        }

        public List<IAction> Actions
        {
            get;
            set;
        }

        public IEnumerable<string> ActionTitles 
        { 
            get 
            { 
                return from a in Actions select a.Title; 
            } 
        }

        public string TargetTeamProject
        {
            get
            {
                return TargetTestPlan.TeamProject;
            }

            set
            {
                TargetTestPlan.TeamProject = value;

                LstWorkItemFields = null;
                LstChangeField = new ObservableCollection<WIFieldValue>();
                AddFieldRow();
            }
        }

        public string SourceTeamPojectCollectionUri { get { return SourceTestPlan.TeamProjectCollection.Uri.ToString(); } }

        public string TargetTeamPojectCollectionUri { get { return TargetTestPlan.TeamProjectCollection.Uri.ToString(); } }
        #endregion

        #region "Public functions"

        public void Load(Uri sourceUri, string sourceTP, Uri targetUri, string targetTP)
        {
            TestPlan tpSource = new TestPlan(this);
            ConnectTeamProject(ref tpSource, sourceUri, sourceTP);
            SourceTestPlan = tpSource;

            TestPlan tpTarget = new TestPlan(this);
            ConnectTeamProject(ref tpTarget, sourceUri, targetTP);
            TargetTestPlan = tpTarget;

            LstChangeField = new ObservableCollection<WIFieldValue>();
            AddFieldRow();
            
            CopyRecursive = false;
        }

        public List<WorkItemFields> LoadFields(TfsTeamProjectCollection tfs, string teamProject)
        {
            List<WorkItemFields> lstFields = new List<WorkItemFields>();
            if (tfs != null && teamProject != null)
            {
                WorkItemStore wiStore = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));

                var categories = wiStore.Projects[teamProject].Categories;

                WorkItemType wt = categories.First(x  => x.ReferenceName == "Microsoft.TestCaseCategory").DefaultWorkItemType;
                foreach (FieldDefinition item in wt.FieldDefinitions)
                {
                    AddField(ref lstFields, teamProject, wiStore, item);
                }
            }

            return lstFields;
        }

        public void cmdConnectSourceTP()
        {
            TestPlan tp = SourceTestPlan;
            ConnectTeamProject(ref tp);
            SourceTestPlan = tp;
        }
        
        public void cmdConnectTargetTP()
        {
            TestPlan tp = TargetTestPlan;
            ConnectTeamProject(ref tp);
            TargetTestPlan = tp;
        }
        
         public void ConnectTeamProject(ref TestPlan tp, Uri tfsUri, string teamProjectName)
        {
            tp.TeamProjectCollection = new TfsTeamProjectCollection(tfsUri);
            tp.TeamProject = teamProjectName;
        }

        public void ConnectTeamProject(ref TestPlan tp)
        {
            TeamProjectPicker pp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
            if (pp.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (pp.SelectedTeamProjectCollection != null)
                {
                    tp.TeamProjectCollection = pp.SelectedTeamProjectCollection;
                    tp.TeamProject = pp.SelectedProjects[0].Name;
                }
            }
        }

        public void cmdDoActions(Window parentWindow)
        {
            TeamExplorerIntergator teIntegrator = new TeamExplorerIntergator();
            teIntegrator.tpCollection = SourceTestPlan.TeamProjectCollection;
            teIntegrator.tpName = SourceTestPlan.TeamProject;

            Dictionary<string, object> sharedVariables = new Dictionary<string, object>();
            sharedVariables.Add("SourceTestTeamProject", SourceTestPlan.TestTeamProject);
            sharedVariables.Add("TargetTestTeamProject", TargetTestPlan.TestTeamProject);
            sharedVariables.Add("TargetTestSuites",     TargetTestPlan.TestSuites);

            sharedVariables.Add("TeamExplorerIntegrator", teIntegrator);

            ProgressDlg progress = new ProgressDlg();
            progress.DoProgress(parentWindow, "Create new iteration", sharedVariables, Actions);

            Actions.Clear();
            TargetTestPlan.TestPlanID = TargetTestPlan.TestPlanID;
        }

        #endregion 

        #region "Internal functions"

        internal void cmdCopy()
        {
            int targetTP = 0;
            if (CreateTargetTestPlan)
            {
            }
            else
            {
                targetTP = TargetTestPlan.TestPlanID;
            }
        }

        internal void cmdAddDeepCopyNode(XmlElement source, XmlElement targetParent)
        {
            CopyNodeDelagate copDelegate = new CopyNodeDelagate(DeepCopyNode);
            Copy(false, source, targetParent, copDelegate);
        }

        internal void cmdAddShallowCopyNode(XmlElement source, XmlElement targetParent)
        {
            CopyNodeDelagate copDelegate = new CopyNodeDelagate(ShallowCopyNode);
            Copy(CopyRecursive, source, targetParent, copDelegate);
        }

        internal void cmdAddTCLinkedQueryAction(WIQLQueryItems itm, XmlElement parentSuiteNode)
        {
            Actions.Add(new StaticSuiteWithTCfromQueryAction(itm.Name, itm.QueryGuid, itm.Path, parentSuiteNode));
            NotifyPropertyChanged("TargetTestSuites");
        }

        internal void AddFieldRow()
        {
            LstChangeField.Add(new WIFieldValue() { Field = LstWorkItemFields[0], Value = string.Empty });
        }

        internal void cmdNewStaticSuite()
        {
            NewStatic((XmlElement)TargetTestPlan.SelectedNode, "New Static Suite");
        }

        internal void UpdateSuiteName(XmlElement e)
        {
            Actions.Add(new RenameSuiteAction(e));

            e.SetAttribute("Edit", "false");
        }
        #endregion

        #region "Private functions"

        private static void AddField(ref List<WorkItemFields> lstFields, string teamProject, WorkItemStore wiStore, FieldDefinition item)
        {
            if (item.IsEditable)
            {
                WorkItemFields fld = new WorkItemFields();
                fld.FieldName = item.Name;
                fld.RefName = item.ReferenceName;
                fld.AllowedValues = new List<KeyValuePair<string, string>>();
                NodeCollection lst;

                switch (fld.RefName)
                {
                    case "System.IterationPath":
                        lst = wiStore.Projects[teamProject].IterationRootNodes;
                        foreach (Node n in lst)
                        {
                            fld.AllowedValues.Add(new KeyValuePair<string, string>(n.Path, n.Name));
                        }

                        lstFields.Add(fld);
                        break;
                    case "System.AreaPath":
                        lst = wiStore.Projects[teamProject].AreaRootNodes;
                        foreach (Node n in lst)
                        {
                            fld.AllowedValues.Add(new KeyValuePair<string, string>(n.Path, n.Name));
                        }

                        lstFields.Add(fld);
                        break;
                    default:
                        if (!(fld.RefName.Contains("System.") || fld.RefName.Contains("Microsoft.")))
                        {
                            foreach (string s in item.AllowedValues)
                            {
                                fld.AllowedValues.Add(new KeyValuePair<string, string>(s, s));
                            }

                            lstFields.Add(fld);
                        }

                        break;
                }
            }
        }
   
        private void Copy(bool recursiveCopy, XmlElement source, XmlElement targetParent, CopyNodeDelagate copyDelegate)
        {
            XmlElement copy = targetParent;
            if (source.Name != "TestPlan")
            {
                copy = copyDelegate(source, targetParent);
                if (recursiveCopy && source.GetAttribute("Type") == TestSuiteEntryType.StaticTestSuite.ToString())
                {
                    foreach (XmlElement x in source.SelectNodes("TestSuite"))
                    {
                        Copy(recursiveCopy, x, copy, copyDelegate);
                    }
                }
            }
            else
            {
                foreach (XmlElement x in source.SelectNodes("TestSuite"))
                {
                    Copy(recursiveCopy, x, copy, copyDelegate);
                }          
            }
        }

        private XmlElement NewStatic(XmlElement targetParent, string name)
        {
            XmlElement copy = targetParent.OwnerDocument.CreateElement("TestSuite");

            XmlAttribute a = targetParent.OwnerDocument.CreateAttribute("Name");
            a.Value = name;
            copy.Attributes.Append(a);

            a = targetParent.OwnerDocument.CreateAttribute("CopyType");
            a.Value = "NewStatic";
            copy.Attributes.Append(a);

            a = targetParent.OwnerDocument.CreateAttribute("Guid");
            a.Value = Guid.NewGuid().ToString();
            copy.Attributes.Append(a);
     
            targetParent.AppendChild(copy);

            NotifyPropertyChanged("TargetTestSuites");

            Actions.Add(new NewStaticSuiteAction(copy, targetParent, name));
            NotifyPropertyChanged("ActionTitles");
            
            return copy;
        }

        private XmlElement DeepCopyNode(XmlElement source, XmlElement targetParent)
        {
            if ((TestSuiteEntryType)Enum.Parse(typeof(TestSuiteEntryType), source.Attributes["Type"].Value) != TestSuiteEntryType.TestCase)
            {
                XmlElement copy = targetParent.OwnerDocument.CreateElement("TestSuite");

                XmlAttribute a = targetParent.OwnerDocument.CreateAttribute("Name");
                a.Value = source.Attributes["Name"].Value.ToString();
                copy.Attributes.Append(a);

                a = targetParent.OwnerDocument.CreateAttribute("CopyType");
                a.Value = "DeepCopy";
                copy.Attributes.Append(a);

                a = targetParent.OwnerDocument.CreateAttribute("Guid");
                a.Value = source.Attributes["Guid"].Value;
                copy.Attributes.Append(a);

                a = targetParent.OwnerDocument.CreateAttribute("SourceSuiteId");
                a.Value = source.Attributes["SuiteId"].Value;
                copy.Attributes.Append(a);

                targetParent.AppendChild(copy);

                NotifyPropertyChanged("TargetTestSuites");

                List<NameValuePair> lst = (from i in LstChangeField select new NameValuePair(i.Field.RefName, i.Value)).ToList();

                Actions.Add(new DeepCopySuiteAction(copy, targetParent, CopyRequirement, lst));
                NotifyPropertyChanged("ActionTitles");
                return copy;
            }
            else
            {
                return null;
            }
        }

        private XmlElement ShallowCopyNode(XmlElement source, XmlElement targetParent)
        {
            XmlElement copy = targetParent.OwnerDocument.CreateElement("TestSuite");

            foreach (XmlAttribute a in source.Attributes)
            {
                if (a.Name != "SuiteId")
                {
                    XmlAttribute newAttrib = targetParent.OwnerDocument.CreateAttribute(a.Name);

                    newAttrib.Value = a.Value;
                    copy.Attributes.Append(newAttrib);
                }
            }

            XmlAttribute copyTypeAttrib = targetParent.OwnerDocument.CreateAttribute("CopyType");
            copyTypeAttrib.Value = "Copy";
            copy.Attributes.Append(copyTypeAttrib);

            targetParent.AppendChild(copy);

            NotifyPropertyChanged("TargetTestSuites");

            Actions.Add(new ShallowCopySuiteAction(copy, targetParent, ConvRequirementToStatic));
            NotifyPropertyChanged("ActionTitles");
            return copy;
        }
        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion     
    }

    [ValueConversion(typeof(bool), typeof(bool))]
    public class InverseBooleanConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(bool))
            {
                throw new InvalidOperationException("The target must be a boolean");
            }

            return !(bool)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion
    }

    public class TestPlan : INotifyPropertyChanged
    {
        #region "Private members"
        private int testPlanId;
        private string testPlanName;
        private string teamProjectName;
        private XmlDocument suiteXMLDoc;
        private ITestManagementService testSvc;
        private ITestManagementTeamProject tstTP;
        private XmlNode selectedNode;
     
        private bool _showTestResult;

        private MTMViewModel parent;

        #endregion

        public TestPlan(MTMViewModel parentModel)
        {
            teamProjectName = string.Empty;
            parent = parentModel;
            Progress = new ProgressIndication();
        }

        #region "Public properties"
        public ProgressIndication Progress { get; set; }

        public TfsTeamProjectCollection TeamProjectCollection
        {
            get;
            set;
        }

        public int TestPlanID
        {
            get
            {
                return testPlanId;
            }

            set
            {
                testPlanId = value;
                ShowTestResult = false;
                NotifyPropertyChanged("TestPlanID");
                Task t = new Task(delegate { TestSuites = LoadTestSuite(); });
                t.Start();
            }
        }

        public string TestPlanName
        {
            get
            {
                return testPlanName;
            }

            set
            {
                testPlanName = value;
                NotifyPropertyChanged("TestPlanName");
            }
        }

        public XmlDocument TestSuites
        {
            get
            {
                return suiteXMLDoc;
            }

            set
            {
                suiteXMLDoc = value;
                NotifyPropertyChanged("TestSuites");
                parent.NotifyPropertyChanged("isReadyForNewSuite");
                parent.NotifyPropertyChanged("isTreeviewReadyForCopy");
            }
        }

        public XmlNode SelectedNode
        {
            get
            {
                return selectedNode;
            }

            set
            {
                selectedNode = value;
                NotifyPropertyChanged("SelectedNode");
                parent.NotifyPropertyChanged("isReadyForNewSuite");
                parent.NotifyPropertyChanged("isTreeviewReadyForCopy");
            }
        }

        public Dictionary<int, string> TestPlanList
        {
            get
            {
                return GetTestPlanList();
            }
        }

        public ITestManagementTeamProject TestTeamProject 
        { 
            get 
            { 
                return tstTP; 
            } 
        }

        public string TeamProject
        {
            get
            {
                return teamProjectName;
            }

            set
            {
                teamProjectName = value;
                testSvc = (ITestManagementService)TeamProjectCollection.GetService(typeof(ITestManagementService));

                tstTP = testSvc.GetTeamProject(TeamProject);
                NotifyPropertyChanged("TeamProject");
                NotifyPropertyChanged("TestPlanList");
            }
        }

        public bool ShowTestResult
        {
            get
            {
                return _showTestResult;
            }

            set
            {
                _showTestResult = value;
                if (ShowTestResult)
                {
                    Task t = new Task(delegate { LoadTestResult(null, null); });
                    t.Start();
                }
                else
                {
                    if (TestSuites != null)
                    {
                        Task t = new Task(delegate { TestSuites = LoadTestSuite(); });
                        t.Start();
                    }
                }

                NotifyPropertyChanged("ShowTestResult");
            }
        }

        #endregion

        internal void LoadTestResult(XElement root, ITestPlan plan)
        {
            if (root == null)
            {
                plan = TestTeamProject.TestPlans.Find(this.TestPlanID);

                this.Progress.JobStatus = JobStatus.inProgress;
                this.Progress.JobProgress = 0;
                this.Progress.Max = plan.QueryTestPoints("Select * from TestPoint").GroupBy(tp => tp.TestCaseId).Count();

                XDocument xDoc = XDocument.Parse(TestSuites.InnerXml);
                root = xDoc.Root;
                LoadTestResult(root, plan);

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xDoc.ToString());
                TestSuites = doc;

                this.Progress.JobStatus = JobStatus.notStarted;
                this.Progress.JobProgress = 0;
            }
            else
            {
                Dictionary<TestOutcome, int> sum = new Dictionary<TestOutcome, int>();

                if (root.Attribute("Type").Value == TestSuiteEntryType.TestCase.ToString())
                {
                    this.Progress.Step();

                    int suiteId = Convert.ToInt32(root.Parent.Attribute("SuiteId").Value);
                    int testCaseId = Convert.ToInt32(root.Attribute("SuiteId").Value);

                    var testpoints = plan.QueryTestPoints(string.Format("SELECT * FROM TestPoint WHERE SuiteId = {0} And TestCaseId = {1}", suiteId, testCaseId));

                    var testResults = TestTeamProject.TestResults.ByTestId(Convert.ToInt32(root.Attribute("SuiteId").Value)).Join(testpoints, tr => tr.TestPointId, tp => tp.Id, (tr, tp) => tr);
                    if (testpoints.Count - testResults.Count() > 0)
                    {
                        AddValueToKey(sum, TestOutcome.NotExecuted, testpoints.Count - testResults.Count());
                    }

                    var lst = from t in testResults group t by t.TestPointId into g select g.OrderByDescending(tt => tt.DateCompleted).First();

                    foreach (ITestResult tr in lst)
                    {
                        AddValueToKey(sum, tr.Outcome, 1);
                    }
                }
                else
                {
                    foreach (XElement x in root.Nodes())
                    {
                        LoadTestResult(x, plan);

                        foreach (string s in Enum.GetNames(typeof(TestOutcome)))
                        {
                            if (x.Attribute(s) != null)
                            {
                                AddValueToKey(sum, (TestOutcome)Enum.Parse(typeof(TestOutcome), s), Convert.ToInt32(x.Attribute(s).Value));
                            }
                        }
                    }
                }

                double total = sum.Sum(k => (int)k.Value);
                double passed = sum.Where(x => x.Key == TestOutcome.Passed).Sum(k => (int)k.Value);
                double failed = sum.Where(x => x.Key == TestOutcome.Failed).Sum(k => (int)k.Value);
                double blocked = sum.Where(x => x.Key == TestOutcome.Blocked).Sum(k => (int)k.Value);

                string testStatus = string.Empty;
                if (total > 0)
                {
                    testStatus = "PartialTested";
                }

                if (passed == total && passed > 0)
                {
                    testStatus = "Passed";
                }

                if (failed > 0)
                {
                    testStatus = "Failed";
                }

                if (blocked > 0)
                {
                    testStatus = "Blocked";
                }

                root.SetAttributeValue("TestStatus", testStatus);

                foreach (KeyValuePair<TestOutcome, int> kvp in sum)
                {
                    root.SetAttributeValue(kvp.Key.ToString(), kvp.Value.ToString());
                    root.SetAttributeValue(kvp.Key.ToString() + "_percentage", (int)((kvp.Value / total) * 100));
                }
            }
        }

        #region "Private Methods"

        internal XmlDocument LoadTestSuite()
        {
            this.Progress.JobStatus = JobStatus.inProgress;
            this.Progress.JobProgress = 0;

            XDocument doc = new XDocument();
            XElement xRoot = new XElement("TestPlan",
                                new XAttribute("Name", "Testplan"),
                                new XAttribute("Type", "none"));
            doc.Add(xRoot);

            if (testPlanId != 0)
            {
                if (TeamProject != null)
                {
                    ITestManagementTeamProject tstTP = testSvc.GetTeamProject(TeamProject);
                    if (tstTP != null)
                    {
                        ITestPlan testplan = tstTP.TestPlans.Find(testPlanId);
                        this.Progress.Max = testplan.QueryTestPoints("Select * from TestPoint").GroupBy(tp  => tp.TestCaseId).Count();
                        IStaticTestSuite tsRoot = testplan.RootSuite;

                        xRoot.Add(new XAttribute("SuiteId", testplan.RootSuite.Id));

                        BuildTree(tsRoot.Entries, xRoot);
                    }
                }
            }

            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(doc.ToString());

            this.Progress.JobStatus = JobStatus.notStarted;

            return xDoc;
        }

        private void BuildTree(ITestSuiteEntryCollection tsCollection, XElement xRoot)
        {
            foreach (ITestSuiteEntry ts in tsCollection.OrderBy(ts  => ts.Title))
            {
                TestSuiteEntryType t = ts.EntryType;

                XElement x = new XElement("TestSuite",
                    new XAttribute("Name", ts.Title),
                    new XAttribute("SuiteId", ts.Id),
                    new XAttribute("Guid", Guid.NewGuid().ToString()),
                    new XAttribute("Type", t));

                xRoot.Add(x);

                switch (ts.EntryType)
                {
                    case TestSuiteEntryType.StaticTestSuite:
                        IStaticTestSuite suite = ts.TestSuite as IStaticTestSuite;
                        if (suite.Entries.Count > 0)
                        {
                            BuildTree(suite.Entries, x);
                        }

                        break;
                    case TestSuiteEntryType.DynamicTestSuite:
                        IDynamicTestSuite dynSuite = ts.TestSuite as IDynamicTestSuite;
                        x.Add(new XAttribute("QueryText", dynSuite.Query.QueryText));

                        if (dynSuite.TestCases.Count > 0)
                        {
                            BuildTree(dynSuite.TestCases, x);
                        }

                        break;
                    case TestSuiteEntryType.RequirementTestSuite:
                        IRequirementTestSuite reqSuite = ts.TestSuite as IRequirementTestSuite;
                        x.SetAttributeValue("Name", reqSuite.Project.WitProject.Store.GetWorkItem(reqSuite.RequirementId).Title);
                        x.Add(new XAttribute("RequirementId", reqSuite.RequirementId));
                        
                        if (reqSuite.TestCases.Count > 0)
                        {
                            BuildTree(reqSuite.TestCases, x);
                        }

                        break;
                    case TestSuiteEntryType.TestCase:
                        this.Progress.Step();
                        x.Add(new XAttribute("TestCaseId", ts.TestCase.Id));
                        break;
                }
            }
        }

        private Dictionary<int, string> GetTestPlanList()
        {
            Dictionary<int, string> lst = new Dictionary<int, string>();

            if (TeamProject != null)
            {
                if (tstTP != null)
                {
                    foreach (ITestPlan tp in tstTP.TestPlans.Query("Select * From TestPlan"))
                    {
                        lst.Add(tp.Id, tp.Name);
                    }
                }
            }

            return lst;
        }
        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion

        private static void AddValueToKey(Dictionary<TestOutcome, int> dictonary, TestOutcome key, int value)
        {
            if (!dictonary.ContainsKey(key))
            {
                dictonary.Add(key, 0);
            }

            dictonary[key] += value;
        }
    }
}
